﻿using System;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Collections.Generic;

namespace UHFReaderDemo
{
    public class UHFReader
    {

        #region PrivateProperty
        private static SerialPort serialport;
        private static Thread RcvThread;
        private static System.Threading.EventWaitHandle ewh;

        private static Byte temp_Command, temp_Status;
        private static Byte[] temp_Payload;

        ///////////////////////////////////////////////////////////////
        private static Thread ReportThread;
        private static String tempDirection;
        private static Byte[] tempFrameData;
        private static System.Threading.EventWaitHandle ewh1;
        ///////////////////////////////////////////////////////////////

        #endregion

        #region PublicProperty

        /// <summary>
        /// 用于指示与读写器连接的串口是否打开。
        /// </summary>
        public static Boolean IsOpen
        {
            get
            {
                try
                {
                    if (serialport == null) return false;
                    return serialport.IsOpen;
                }
                catch { return false; }
            }
        }

        #endregion

        #region Public Event

        public delegate void TagDetectedDel(Byte Command, Byte Status, Byte[] TagUII);
        public static event TagDetectedDel TagDetected;
        public delegate void ReturnSelectRecordDel(Byte Command, Byte Status, Byte[] SelectRecord);
        public static event ReturnSelectRecordDel ReturnSelectRecord;
        public delegate void AdvancedInventoryCompleteDel(Byte Command, Byte Status, Int32 TagNumber);
        public static event AdvancedInventoryCompleteDel AdvancedInventoryComplete;
        public delegate void ReturnTagRecordDel(Byte Command, Byte Status, Byte[] TagRecord);
        public static event ReturnTagRecordDel ReturnTagRecord;
        ////////////////////////////////////////////////////
        public delegate void SendAndReceiveDel(String Direction, Byte[] Frame);
        public static event SendAndReceiveDel SendAndReceive;
        ////////////////////////////////////////////////////
        #endregion


        #region PublicMethod

        /// <summary>
        /// 打开与设备连接的串口
        /// </summary>
        /// <param name="PortName">串口号，如"COM3"</param>
        /// <param name="BaudRate">波特率，默认为57600</param>
        /// <returns>0x00:打开成功;0x01:打开失败，原因是已经处于打开状态;0x02:打开失败，原因是串口不存在等等。
        /// </returns>
        public static ErrorCode OpenAndConnect(String PortName, Int32 BaudRate)
        {
            if (IsOpen)
            { return ErrorCode.AllDone; }
            try
            {
                serialport = new SerialPort(PortName, BaudRate, Parity.None, 8, StopBits.One);
                serialport.ReadTimeout = 500;
                serialport.Open();
                if (IsOpen)
                {
                    ewh = new System.Threading.EventWaitHandle(false, EventResetMode.ManualReset);
                    RcvThread = new Thread(new ThreadStart(RcvData));
                    RcvThread.IsBackground = true;
                    RcvThread.Start();
                    /////////////////////////////////////////////////////
                    ewh1 = new System.Threading.EventWaitHandle(false, EventResetMode.AutoReset);
                    ReportThread = new Thread(new ThreadStart(ReportFrame));
                    ReportThread.IsBackground = true;
                    ReportThread.Start();
                    /////////////////////////////////////////////////////
                    return ErrorCode.AllDone;
                }
                else
                { return ErrorCode.SerialPortError; }
            }
            catch { return ErrorCode.SerialPortError; }
        }

        public static ErrorCode OpenAndConnect(String PortName)
        {
            return OpenAndConnect(PortName, 57600);
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <returns>0x00:关闭成功;0x01:关闭失败，原因是尚未打开;0x02:关闭操作执行失败。
        /// </returns>
        public static ErrorCode CloseAndDisconnect()
        {
            if (!IsOpen)
            {
                return ErrorCode.AllDone;
            }
            try
            {
                serialport.Close();
                if (!IsOpen)
                { return ErrorCode.AllDone; }
                else
                { return ErrorCode.SerialPortError; }
            }
            catch
            { return ErrorCode.SerialPortError; }
        }

        /// <summary>
        /// 读取与读写器的连接状态
        /// </summary>
        /// <param name="PaStatus">布尔型，用于指示是否连接成功</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode GetPaStatus(out Boolean PaStatus, Boolean CRCFlag)
        {
            PaStatus = false;
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x00, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer();
                ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                //if (Command != 0x00)
                //{ return ErrorCode.CommandError; }
                //if (Payload.Length != 0x00)
                //{ return ErrorCode.PayloadError; }
                //if ((Status & 0x81) == 0)
                //{}
                PaStatus = true;
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 获取读写器功率设置
        /// </summary>
        /// <param name="Power">
        /// 读写器返回的功率字节
        /// 最高位表示功率控制方式：0代表手动，1代表自动
        /// 低7位为输出功率，单位dbm
        /// </param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode GetPower(out Byte Power, Boolean CRCFlag)
        {
            Power = 0x00;
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x01, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer();
                ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x01)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                { return ErrorCode.StatusError; }
                if (Payload.Length != 0x01)
                { return ErrorCode.PayloadError; }
                Power = Payload[0];
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 设置读写器功率
        /// </summary>
        /// <param name="Power">
        /// 读写器的功率字节
        /// 最高位表示功率控制方式：0代表手动，1代表自动
        /// 低7位为输出功率，单位dbm
        /// </param>
        /// <param name="Option">
        /// 功率设置控制字节
        /// 最低位为输出功率控制位：1表示POWER字节的Bit6~0有效，0表示POWER字节的Bit6~0无效
        /// 次低位为功率控制模式控制位：1表示POWER字节的Bit7有效，0表示POWER字节的Bit7无效
        /// </param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode SetPower(Byte Power, Byte Option, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x02, new Byte[] { Option, Power }, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer();
                ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x02)
                { return ErrorCode.CommandError; }
                if (Payload.Length != 0x00)
                { return ErrorCode.PayloadError; }
                if (Status != 0x00)
                { return ErrorCode.StatusError; }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 获取读写器频率设置
        /// </summary>
        /// <param name="Frequency">
        /// 读写器的频率设置，长7字节，其中
        /// 1:频率工作模式Frequency Mode; 
        /// 2:频率基数Frequency Base;
        /// 3 4:起始频率Begin Frequency;
        /// 5:频道数Count;
        /// 6:频道带宽SPC;
        /// 7:调频顺序方式FREHOP.
        /// </param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode GetFrequency(out Byte[] Frequency, Boolean CRCFlag)
        {
            Frequency = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x05, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x05)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                { return ErrorCode.StatusError; }
                if (Payload.Length != 0x07)
                { return ErrorCode.PayloadError; }
                Frequency = Payload;
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 设置读写器频率
        /// </summary>
        /// <param name="Frequency">
        /// 读写器的频率设置，长7字节，其中
        /// 1:频率工作模式Frequency Mode; 
        /// 2:频率基数Frequency Base;
        /// 3 4:起始频率Begin Frequency;
        /// 5:频道数Count;
        /// 6:频道带宽SPC;
        /// 7:调频顺序方式FREHOP.
        /// </param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode SetFrequency(Byte[] Frequency, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x06, Frequency, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x06)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                { return ErrorCode.StatusError; }
                if (Payload.Length != 0x00)
                { return ErrorCode.PayloadError; }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 启动读写器的识别循环
        /// </summary>
        /// <param name="AntiFlag">
        /// 是否启用防碰撞识别功能
        /// True:启用防碰撞识别多标签
        /// False:不启用防碰撞识别
        /// </param>
        /// <param name="InitQ">
        /// 防碰撞时的初始Q值
        /// 仅在启用防碰撞识别时有效
        /// 允许的值为0~15，默认值为3
        /// </param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode Inventory(Boolean AntiFlag, Byte InitQ, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame;
            if (AntiFlag)
            {
                Frame = EncapFrame(0x11, new Byte[] { InitQ }, CRCFlag);
            }
            else
            {
                Frame = EncapFrame(0x10, new Byte[0], CRCFlag);
            }
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (!((Command == 0x10) || (Command == 0x11)))
                { return ErrorCode.CommandError; }
                if (Status != 0x01)
                { return ErrorCode.StatusError; }
                if (Payload.Length != 0x00)
                { return ErrorCode.PayloadError; }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        ///// <summary>
        ///// 读取读写器返回的标签UII
        ///// </summary>
        ///// <param name="UII">读写器返回的标签UII</param>
        ///// <returns>命令执行情况</returns>
        //public static ErrorCode GetReceived(out Byte[] UII)
        //{
        //        UII = new Byte[0];
        //        if (!IsOpen)
        //        { return ErrorCode.NotOpenError; }
        //        Byte Command, Status;
        //        Byte[] Payload;
        //        ErrorCode ec = RcvFrame(out Command, out Status, out Payload);
        //        if (ec != ErrorCode.AllDone)
        //        { return ec; }
        //        //分析响应帧数据
        //        if ((Command != 0x10) || (Command != 0x11))
        //        { return ErrorCode.CommandError; }
        //        if (Status != 0x00)
        //        { return ErrorCode.StatusError; }
        //        UII = Payload;
        //        return ErrorCode.AllDone; 
        //}

        /// <summary>
        /// 单步识别标签，并读取标签UII
        /// </summary>
        /// <param name="UII">读写器返回的标签UII</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode InventorySingle(out Byte[] UII, Boolean CRCFlag)
        {
            UII = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x18, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x18)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                { return ErrorCode.StatusError; }
                UII = Payload;
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 停止读写器的当前操作(主要用于停止读写器的Inventory操作)
        /// </summary>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode StopInventory(Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x12, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            return ErrorCode.AllDone;
            //if (ewh.WaitOne(500, false))
            //{
            //        Byte Command = temp_Command;
            //        Byte Status = temp_Status;
            //        Byte[] Payload = temp_Payload;
            //        //分析响应帧数据
            //        if (Command != 0x12)
            //        { return ErrorCode.CommandError; }
            //        if (Status != 0x00)
            //        { return ErrorCode.StatusError; }
            //        return ErrorCode.AllDone;
            //}
            //else
            //{ return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 读取标签数据(指定UII)
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="Bank">数据区类型</param>
        /// <param name="Pointer">起始地址的偏移量</param>
        /// <param name="Count">数据长度，以字(2Byte)为单位</param>
        /// <param name="UII">标签的 UII</param>
        /// <param name="Data">返回值，读取到的数据</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ReadData(Byte[] AccessPassword, Byte Bank, Int32 Pointer, Byte Count, Byte[] UII, out Byte[] Data, Boolean CRCFlag)
        {
            Data = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //把Pointer转换成EBV数据
            Byte[] PTR = Int32ToEBV(Pointer);
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            CMDPayload.Add(Bank);
            for (Int32 i = 0; i < PTR.Length; i++)
            { CMDPayload.Add(PTR[i]); }
            CMDPayload.Add(Count);
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x13, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                //分析响应帧数据
                if (Command != 0x13)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                //获取数据
                if (Count > 0)
                { Data = Payload; }
                else
                {
                    if (Payload.Length > 2)
                    {
                        Data = new Byte[Payload.Length - 2];
                        for (Int32 i = 0; i < Data.Length; i++)
                        { Data[i] = Payload[2 + i]; }
                    }
                    else
                    { Data = Payload; }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 读取标签数据(不指定UII)
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="Bank">数据区类型</param>
        /// <param name="Pointer">起始地址的偏移量</param>
        /// <param name="Count">数据长度，以字(2Byte)为单位</param>
        /// <param name="UII">返回值，标签的UII</param>
        /// <param name="Data">返回值，读取到的数据</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ReadDataSingle(Byte[] AccessPassword, Byte Bank, Int32 Pointer, Byte Count, out Byte[] UII, out Byte[] Data, Boolean CRCFlag)
        {
            Data = new Byte[0];
            UII = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //把Pointer转换成EBV数据
            Byte[] PTR = Int32ToEBV(Pointer);
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            CMDPayload.Add(Bank);
            for (Int32 i = 0; i < PTR.Length; i++)
            { CMDPayload.Add(PTR[i]); }
            CMDPayload.Add(Count);
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x20, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x20)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                //获取数据
                if (Count > 0)
                {
                    Data = new Byte[Count * 2];
                    for (Int32 i = 0; i < Data.Length; i++)
                    { Data[i] = Payload[i]; }
                    UII = new Byte[Payload.Length - Data.Length];
                    for (Int32 i = 0; i < UII.Length; i++)
                    { UII[i] = Payload[Data.Length + i]; }
                }
                else
                {
                    Int32 DataLength = Payload[0] * 256 + Payload[1];
                    Data = new Byte[DataLength];
                    for (Int32 i = 0; i < Data.Length; i++)
                    { Data[i] = Payload[2 + i]; }
                    UII = new Byte[Payload.Length - DataLength - 2];
                    for (Int32 i = 0; i < UII.Length; i++)
                    { UII[i] = Payload[Data.Length + 2 + i]; }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 写入标签数据(指定UII)
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="Bank">数据区类型</param>
        /// <param name="Pointer">起始地址的偏移量</param>
        /// <param name="Count">数据长度，以字(2Byte)为单位</param>
        /// <param name="UII">标签的UII</param>
        /// <param name="Data">待写入的数据，长度不小于Count*2</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode WriteData(Byte[] AccessPassword, Byte Bank, Int32 Pointer, Byte Count, Byte[] UII, Byte[] Data, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            if (Data.Length < (Count * 2))
            { return ErrorCode.DataLengthError; }
            //把Pointer转换成EBV数据
            Byte[] PTR = Int32ToEBV(Pointer);
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            CMDPayload.Add(Bank);
            for (Int32 i = 0; i < PTR.Length; i++)
            { CMDPayload.Add(PTR[i]); }
            CMDPayload.Add(Count);
            for (Int32 i = 0; i < Count * 2; i++)
            { CMDPayload.Add(Data[i]); }
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x14, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x14)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 写入标签数据(不指定UII)
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="Bank">数据区类型</param>
        /// <param name="Pointer">起始地址的偏移量</param>
        /// <param name="Count">数据长度，以字(2Byte)为单位</param>
        /// <param name="UII">返回值，标签的UII</param>
        /// <param name="Data">待写入的数据，长度不小于Count*2</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode WriteDataSingle(Byte[] AccessPassword, Byte Bank, Int32 Pointer, Byte Count, out Byte[] UII, Byte[] Data, Boolean CRCFlag)
        {
            UII = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            if (Data.Length < (Count * 2))
            { return ErrorCode.DataLengthError; }
            //把Pointer转换成EBV数据
            Byte[] PTR = Int32ToEBV(Pointer);
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            CMDPayload.Add(Bank);
            for (Int32 i = 0; i < PTR.Length; i++)
            { CMDPayload.Add(PTR[i]); }
            CMDPayload.Add(Count);
            for (Int32 i = 0; i < Count * 2; i++)
            { CMDPayload.Add(Data[i]); }
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x21, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x21)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                UII = Payload;
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 擦除标签数据
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="Bank">数据区类型</param>
        /// <param name="Pointer">起始地址的偏移量</param>
        /// <param name="Count">数据长度，以字(2Byte)为单位</param>
        /// <param name="UII">标签的UII</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode EraseData(Byte[] AccessPassword, Byte Bank, Int32 Pointer, Byte Count, Byte[] UII, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //把Pointer转换成EBV数据
            Byte[] PTR = Int32ToEBV(Pointer);
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            CMDPayload.Add(Bank);
            for (Int32 i = 0; i < PTR.Length; i++)
            { CMDPayload.Add(PTR[i]); }
            CMDPayload.Add(Count);
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x15, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x15)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 锁定标签的指定数据区
        /// </summary>
        /// <param name="AccessPassword">访问密钥，4个字节</param>
        /// <param name="LockData">锁定操作参数，3个字节</param>
        /// <param name="UII">标签的UII</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode LockMemory(Byte[] AccessPassword, Byte[] LockData, Byte[] UII, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(AccessPassword[i]); }
            for (Int32 i = 0; i < 3; i++)
            { CMDPayload.Add(LockData[i]); }
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x16, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x16)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 销毁指定的标签
        /// </summary>
        /// <param name="KillPassword">销毁密钥，4个字节</param>
        /// <param name="UII">标签的UII</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode KillTag(Byte[] KillPassword, Byte[] UII, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            for (Int32 i = 0; i < 4; i++)
            { CMDPayload.Add(KillPassword[i]); }
            for (Int32 i = 0; i < UII.Length; i++)
            { CMDPayload.Add(UII[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x17, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x17)
                { return ErrorCode.CommandError; }
                if (Status != 0x00)
                {
                    if ((Status == 0x81) && (Payload.Length == 1))
                    {
                        switch (Payload[0])
                        {
                            case 0x00:
                                return ErrorCode.OtherErrorCode;
                            case 0x03:
                                return ErrorCode.OverflowErrorCode;
                            case 0x04:
                                return ErrorCode.LockErrorCode;
                            case 0x0B:
                                return ErrorCode.PowerLackErrorCode;
                            default:
                                return ErrorCode.UnknownErrorCode;
                        }
                    }
                    else
                    {
                        return ErrorCode.StatusError;
                    }
                }
                return ErrorCode.AllDone;
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// 读取读写器的寄存器数据
        /// 注意1：RegAddress+RegLength不能大于512
        /// </summary>
        /// <param name="RegAddress">寄存器数据的起始地址</param>
        /// <param name="RegLength">寄存器数据长度，以字节为单位</param>
        /// <param name="RegValue">返回值，返回的寄存器数据</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ReadReg(Int32 RegAddress, Int32 RegLength, out Byte[] RegValue, Boolean CRCFlag)
        {
            RegValue = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            if ((RegAddress + RegLength) > 512)
            { return ErrorCode.ParameterError; }
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            CMDPayload.Add((Byte)(RegAddress / 256));
            CMDPayload.Add((Byte)(RegAddress % 256));
            CMDPayload.Add((Byte)(RegLength / 256));
            CMDPayload.Add((Byte)(RegLength % 256));
            //封装命令帧
            Byte[] Frame = EncapFrame(0x30, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x30)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        RegValue = Payload;
                        return ErrorCode.AllDone;
                    case 0x81:
                        return ErrorCode.ParameterError;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 设置读写器的寄存器数据
        /// 注意1：RegAddress+RegLength不能大于512
        /// 注意2：RegValue的字节长度应等于RegLength
        /// </summary>
        /// <param name="RegAddress">寄存器数据的起始地址</param>
        /// <param name="RegLength">寄存器数据长度，以字节为单位</param>
        /// <param name="RegValue">待写入的寄存器数据</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ReadReg(Int32 RegAddress, Int32 RegLength, Byte[] RegValue, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            if ((RegAddress + RegLength) > 512)
            { return ErrorCode.ParameterError; }
            if (RegValue.Length != RegLength)
            { return ErrorCode.DataLengthError; }
            //构成命令帧payload
            List<Byte> CMDPayload = new List<byte>();
            CMDPayload.Add((Byte)(RegAddress / 256));
            CMDPayload.Add((Byte)(RegAddress % 256));
            CMDPayload.Add((Byte)(RegLength / 256));
            CMDPayload.Add((Byte)(RegLength % 256));
            for (Int32 i = 0; i < RegValue.Length; i++)
            { CMDPayload.Add(RegValue[i]); }
            //封装命令帧
            Byte[] Frame = EncapFrame(0x31, CMDPayload.ToArray(), CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x31)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    case 0x81:
                        return ErrorCode.ParameterError;
                    case 0x82:
                        return ErrorCode.ReadOnlyError;
                    case 0x83:
                        return ErrorCode.DataLengthError;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 恢复读写器寄存器的出厂默认值
        /// </summary>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ResetReg(Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x32, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x32)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 将当前用户设置由RAM保存到FLASH，以便掉电重启也能保持
        /// 保存的信息包括功率设置、频率设置、BLF设置、波特率设置以及当前寄存器设置
        /// </summary>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode SaveReg(Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x33, new Byte[0], CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x33)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 用于添加Select记录
        /// </summary>
        /// <param name="SRecord">Select记录数据</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode AddSelect(Byte[] SRecord, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x38, SRecord, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x38)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    case 0x80:
                        return ErrorCode.OtherSelectError;
                    case 0x81:
                        return ErrorCode.OverflowSelectError;
                    case 0x82:
                        return ErrorCode.ReadOnlySelectError;
                    case 0x83:
                        return ErrorCode.UnknowSelectError;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 用于删除Select记录
        /// </summary>
        /// <param name="SRecord">Select记录序号</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode DeleteSelect(Byte SIndex, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x39, new Byte[] { SIndex }, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x39)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    case 0x80:
                        return ErrorCode.OtherSelectError;
                    case 0x81:
                        return ErrorCode.OverflowSelectError;
                    case 0x82:
                        return ErrorCode.ReadOnlySelectError;
                    case 0x83:
                        return ErrorCode.UnknowSelectError;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 用于读取Select记录，正常情况下，读写器会返回SNumber+1个响应帧，
        /// 第一个响应帧表示读写器正确接收了该命令，
        /// 后面的每个数据帧包含一个Select记录，因此需要使用GetSelect获取这些Select记录
        /// 当SNumber=0时，读写器会返回所有的Select记录
        /// </summary>
        /// <param name="SIndex">需要读取的Select记录的起始序号</param>
        /// <param name="SNumber">需要读取的Select记录的数量</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ReadSelect(Byte SIndex, Byte SNumber, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x3A, new Byte[] { SIndex, SNumber }, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x3A)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x01:
                        return ErrorCode.AllDone;
                    default:
                        return ErrorCode.UnknownError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        ///// <summary>
        ///// 用于获取与ReadSelect命令相应的后续响应包中的Select记录
        ///// </summary>
        ///// <param name="SRecord">返回值，Select记录数据</param>
        ///// <param name="IsFollowed">返回值，用于指示后面是否还有包含Select记录的响应包</param>
        ///// <param name="CRCFlag">CRC标志</param>
        ///// <returns>命令执行情况</returns>
        //public static ErrorCode GetSelect(out Byte[] SRecord,out Boolean IsFollowed, Boolean CRCFlag)
        //{
        //        IsFollowed = false;
        //        SRecord = new Byte[0];
        //        if (!IsOpen)
        //        { return ErrorCode.NotOpenError; }
        //        //构成命令帧payload
        //        //封装命令帧
        //        //Byte[] Frame = EncapFrame(0x3A, new Byte[] { SIndex, SNumber }, CRCFlag);
        //        //发送命令帧
        //        //try
        //        //{
        //        //        serialport.DiscardInBuffer();ewh.Reset();
        //        //        serialport.Write(Frame, 0, Frame.Length);
        //        //}
        //        //catch
        //        //{ return ErrorCode.SendTimeOut; }
        //        //等待下位机响应
        //        //Thread.Sleep(500);
        //        //接收、分析处理响应帧
        //        Byte Command, Status;
        //        Byte[] Payload;
        //        ErrorCode ec = RcvFrame(out Command, out Status, out Payload);
        //        if (ec != ErrorCode.AllDone)
        //        { return ec; }
        //        //分析响应帧数据
        //        if (Command != 0x3A)
        //        { return ErrorCode.CommandError; }
        //        switch (Status)
        //        {
        //                case 0x00:
        //                        IsFollowed = true;
        //                        SRecord = Payload;
        //                        return ErrorCode.AllDone;
        //                case 0x01:
        //                case 0x02:
        //                        IsFollowed = false;
        //                        SRecord = Payload;
        //                        return ErrorCode.AllDone;
        //                case 0x03:
        //                        return ErrorCode.SRecordSelectError;
        //                case 0x80:
        //                        return ErrorCode.OtherSelectError;
        //                case 0x81:
        //                        return ErrorCode.OverflowSelectError;
        //                default:
        //                        return ErrorCode.UnknowSelectError;
        //        }
        //}

        /// <summary>
        /// 用于选择发送的Select命令参数
        /// </summary>
        /// <param name="SIndex">需要选择的SRecord的起始序号</param>
        /// <param name="SNumber">需要选择的SRecord的个数</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode ChooseSelect(Byte SIndex, Byte SNumber, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x3B, new Byte[] { SIndex, SNumber }, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x3B)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    case 0x80:
                        return ErrorCode.OverflowSelectError;
                    default:
                        return ErrorCode.UnknowSelectError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }

        /// <summary>
        /// 用于启动高级识别
        /// </summary>
        /// <param name="SIndex">发送SRecord中的Select命令的起始序号</param>
        /// <param name="SNumber">发送SRecord中的Select命令的个数</param>
        /// <param name="SST">发送Sel、Session、Target的参数</param>
        /// <param name="InitQ">防碰撞起始Q值</param>
        /// <param name="CRCFlag">CRC标志</param>
        /// <returns>命令执行情况</returns>
        public static ErrorCode AdvanceInventory(Byte SIndex, Byte SNumber, Byte SST, Byte InitQ, Boolean CRCFlag)
        {
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //构成命令帧payload
            //封装命令帧
            Byte[] Frame = EncapFrame(0x40, new Byte[] { SIndex, SNumber, SST, InitQ }, CRCFlag);
            //发送命令帧
            try
            {
                serialport.DiscardInBuffer(); ewh.Reset();
                serialport.Write(Frame, 0, Frame.Length);
            }
            catch
            { return ErrorCode.SendTimeOut; }
            if (ewh.WaitOne(500, false))
            {
                Byte Command = temp_Command;
                Byte Status = temp_Status;
                Byte[] Payload = temp_Payload;
                //分析响应帧数据
                if (Command != 0x40)
                { return ErrorCode.CommandError; }
                switch (Status)
                {
                    case 0x00:
                        return ErrorCode.AllDone;
                    case 0x80:
                        return ErrorCode.OverflowSelectError;
                    default:
                        return ErrorCode.UnknowSelectError;
                }
            }
            else
            { return ErrorCode.ReceiveTimeOut; }
        }


        #endregion

        #region PrivateMethod

        /// <summary>
        /// 整数到EBV数据的转换
        /// </summary>
        /// <param name="Integer">整数</param>
        /// <returns>返回的EBV数据</returns>
        private static Byte[] Int32ToEBV(Int32 Integer)
        {
            List<Byte> data = new List<byte>();
            Boolean Flag = false;
            while (Integer != 0)
            {
                if (Flag)
                {
                    data.Insert(0, (Byte)(((Byte)(Integer % 128)) | 0x80));
                }
                else
                {
                    data.Insert(0, (Byte)(Integer % 128));
                    Flag = true;
                }
                Integer = Integer / 128;
            }
            return data.ToArray();
        }

        /// <summary>
        /// 将字节数组转换为十六进制的字符串
        /// </summary>
        /// <param name="array">字节数组</param>
        /// <returns>字符串</returns>
        private static String ByteArrayToString(Byte[] array)
        {
            StringBuilder sb = new StringBuilder();
            foreach (Byte a in array)
            { sb = sb.Append(a.ToString("X2")); }
            return sb.ToString();
        }
        /// <summary>
        /// 将字节数组转换为十六进制的字符串
        /// </summary>
        /// <param name="array">字节数组</param>
        /// <param name="StartPos">起始位置</param>
        /// <param name="Length">长度</param>
        /// <returns>字符串</returns>
        private static String ByteArrayToString(Byte[] array, Int32 StartPos, Int32 Length)
        {
            StringBuilder sb = new StringBuilder();
            for (Int32 index = StartPos; index < StartPos + Length; index++)
            { sb = sb.Append(array[index].ToString("X2")); }
            return sb.ToString();
        }

        /// <summary>
        /// 将十六进制的字符串转换为字节数组
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>字节数组</returns>
        private static Byte[] StringToByteArray(String str)
        {
            Byte[] data = new Byte[str.Length / 2];
            for (Int32 i = 0; i < data.Length; i++)
            {
                data[i] = Convert.ToByte(str.Substring(i * 2, 2), 16);
            }
            return data;
        }

        /// <summary>
        /// 一个字节数据转换成二进制字符串，长度为8
        /// </summary>
        /// <param name="data">字节数据</param>
        /// <returns>返回的二进制形式字符串</returns>
        private static String ToBinaryString(Byte data)
        {
            string temp = Convert.ToString(data, 2);
            while (temp.Length < 8)
            {
                temp = '0' + temp;
            }
            return temp;
        }
        /// <summary>
        /// 一个Uint16数据转换成二进制字符串，长度为16
        /// </summary>
        /// <param name="data">字节数据</param>
        /// <returns>返回的二进制形式字符串</returns>
        private static String ToBinaryString(UInt16 data)
        {
            string temp = Convert.ToString(data, 2);
            while (temp.Length < 16)
            {
                temp = '0' + temp;
            }
            return temp;
        }
        /// <summary>
        /// 一个UInt32数据转换成二进制字符串，长度为32
        /// </summary>
        /// <param name="data">字节数据</param>
        /// <returns>返回的二进制形式字符串</returns>
        private static String ToBinaryString(UInt32 data)
        {
            string temp = Convert.ToString(data, 2);
            while (temp.Length < 32)
            {
                temp = '0' + temp;
            }
            return temp;
        }
        /// <summary>
        /// CRC-16的计算
        /// </summary>
        /// <param name="frame">字节数组</param>
        /// <param name="offset">偏移量</param>
        /// <param name="datalength">长度</param>
        private static void CalculateCRC(ref Byte[] frame, Int32 offset, Int32 datalength)
        {
            UInt16 crc16_preset = 0xFFFF;
            UInt16 RFCRC16_POLYNOM = 0x8408;
            UInt16 CRC16, m;
            Byte n;
            CRC16 = crc16_preset;
            for (m = 0; m < datalength; m++)
            {
                CRC16 ^= (UInt16)(frame[offset + m] & 0xff);

                for (n = 0; n < 8; n++)
                {
                    if ((CRC16 & 0x0001) > 0)
                        CRC16 = (UInt16)((CRC16 >> 1) ^ RFCRC16_POLYNOM);
                    else
                        CRC16 = (UInt16)(CRC16 >> 1);
                }
            }
            frame[offset + datalength] = (Byte)(CRC16 % 256);
            frame[offset + datalength + 1] = (Byte)(CRC16 / 256);
        }

        /// <summary>
        /// CRC-16的校验
        /// </summary>
        /// <param name="frame">字节数组</param>
        /// <returns>布尔值</returns>
        private static Boolean CheckCRC(Byte[] frame)
        {
            Int32 length = frame.Length;
            Byte LowByte, UperByte;
            UperByte = frame[length - 1];
            LowByte = frame[length - 2];
            CalculateCRC(ref frame, 0, length - 2);
            if ((UperByte == frame[length - 1]) && (LowByte == frame[length - 2]))
            { return true; }
            else
            { return false; }
        }

        /// <summary>
        /// 对数据帧执行的字节插入，这是在发送数据帧之前的最后一步操作
        /// 若数据帧中包含帧头和帧尾，ByteInsert( FrameData,1,FrameData.Length-2)
        /// 若数据帧中不包含帧头和帧尾，ByteInsert( FrameData,0,FrameData.Length)
        /// </summary>
        /// <param name="FrameData">字节插入前的帧数据</param>
        /// <param name="Index">起始位置</param>
        /// <param name="Count">长度</param>
        /// <returns>字节插入后的帧数据</returns>
        private static Byte[] ByteInsert(Byte[] FrameData, Int32 Index, Int32 Count)
        {
            List<Byte> Frame = new List<byte>();
            for (Int32 i = 0; i < Index; i++)
            {
                Frame.Add(FrameData[i]);
            }
            Int32 EndIndex = Index + Count;
            for (Int32 i = Index; i < EndIndex; i++)
            {
                switch (FrameData[i])
                {
                    case 0xAA:
                    case 0x55:
                    case 0xFF:
                        Frame.Add(0xFF);
                        Frame.Add(FrameData[i]);
                        break;
                    default:
                        Frame.Add(FrameData[i]);
                        break;
                }
            }
            for (Int32 i = EndIndex; i < FrameData.Length; i++)
            {
                Frame.Add(FrameData[i]);
            }
            return Frame.ToArray();
        }

        /// <summary>
        /// 封装数据帧(已执行字节插入操作)
        /// </summary>
        /// <param name="Command">命令码</param>
        /// <param name="Payload">有效载荷</param>
        /// <returns>返回的帧数据(已执行字节插入操作)</returns>
        private static Byte[] EncapFrame(Byte Command, Byte[] Payload, Boolean CRCFlag)
        {
            List<Byte> Frame = new List<byte>();
            Frame.Add(0xAA);//帧头
                            //考虑EBV
            if (CRCFlag)//含两个字节的CRC校验
            {
                if (Payload.Length < 124)//Length为一个字节
                { Frame.Add((Byte)(Payload.Length + 4)); }
                else//Length为两个字节
                {
                    Frame.Add((Byte)(((Payload.Length + 4) / 128) | 0x80)); //高字节在前，延伸位为1
                    Frame.Add((Byte)((Payload.Length + 4) % 128));           //低字节在前，延伸位为0
                }
                Frame.Add((Byte)(Command | 0x80));
                for (Int32 i = 0; i < Payload.Length; i++)
                { Frame.Add(Payload[i]); }
                Frame.Add(0x00);//CRC高字节
                Frame.Add(0x00);//CRC低字节
                Frame.Add(0x55);//帧尾
                Byte[] FrameData = Frame.ToArray();
                CalculateCRC(ref FrameData, 1, FrameData.Length - 4);  //计算CRC校验
                Byte[] ReturnData = ByteInsert(FrameData, 1, FrameData.Length - 2);    //执行字节插入
                                                                                       ////////////////////////////////////////////////////
                tempDirection = "发送";
                tempFrameData = ReturnData;
                ewh1.Set();
                ////////////////////////////////////////////////////
                return ReturnData;
            }
            else//不含两个字节的CRC校验
            {
                if (Payload.Length < 126)//Length为一个字节
                { Frame.Add((Byte)(Payload.Length + 2)); }
                else//Length为两个字节
                {
                    Frame.Add((Byte)(((Payload.Length + 2) / 128) | 0x80)); //高字节在前，延伸位为1
                    Frame.Add((Byte)((Payload.Length + 2) % 128));           //低字节在前，延伸位为0
                }
                Frame.Add((Byte)(Command & 0x7F));
                for (Int32 i = 0; i < Payload.Length; i++)
                { Frame.Add(Payload[i]); }
                Frame.Add(0x55);//帧尾
                Byte[] FrameData = Frame.ToArray();
                Byte[] ReturnData = ByteInsert(FrameData, 1, FrameData.Length - 2);    //执行字节插入
                                                                                       ////////////////////////////////////////////////////
                tempDirection = "发送";
                tempFrameData = ReturnData;
                ewh1.Set();
                ////////////////////////////////////////////////////
                return ReturnData;
            }
        }

        ////////////////////////////////////////////////
        private static void ReportFrame()
        {
            String Direction;
            Byte[] FrameData;
            ewh1.Reset();
            while (IsOpen)
            {
                ewh1.WaitOne();
                Direction = tempDirection;
                FrameData = tempFrameData;
                SendAndReceive(Direction, FrameData);
            }
        }
        ////////////////////////////////////////////////

        /// <summary>
        /// 接收数据的子线程代码
        /// 该线程在打开串口时启动，关闭串口时自动结束
        /// </summary>
        private static void RcvData()
        {
            Byte Command, Status;
            Byte[] Payload;
            while (IsOpen)
            {
                if (RcvFrame(out Command, out Status, out Payload) == ErrorCode.AllDone)
                {
                    switch (Command)
                    {
                        case 0x10:
                            if (Payload.Length == 0)
                            {
                                temp_Command = Command;
                                temp_Status = Status;
                                temp_Payload = Payload;
                                ewh.Set();
                            }
                            else
                            {
                                TagDetected(Command, Status, Payload);
                            }
                            break;
                        case 0x11:
                            if (Payload.Length == 0)
                            {
                                temp_Command = Command;
                                temp_Status = Status;
                                temp_Payload = Payload;
                                ewh.Set();
                            }
                            else
                            {
                                TagDetected(Command, Status, Payload);
                            }
                            break;
                        case 0x3A:
                            if (Payload.Length == 0)
                            {
                                temp_Command = Command;
                                temp_Status = Status;
                                temp_Payload = Payload;
                                ewh.Set();
                            }
                            else
                            {
                                ReturnSelectRecord(Command, Status, Payload);
                            }
                            break;
                        case 0x40:
                            if (Payload.Length == 0)
                            {
                                temp_Command = Command;
                                temp_Status = Status;
                                temp_Payload = Payload;
                                ewh.Set();
                            }
                            else
                            {
                                AdvancedInventoryComplete(Command, Status, Payload[0] * 256 + Payload[1]);
                            }
                            break;
                        case 0x42:
                            if (Payload.Length == 0)
                            {
                                temp_Command = Command;
                                temp_Status = Status;
                                temp_Payload = Payload;
                                ewh.Set();
                            }
                            else
                            {
                                ReturnTagRecord(Command, Status, Payload);
                            }
                            break;
                        default:
                            temp_Command = Command;
                            temp_Status = Status;
                            temp_Payload = Payload;
                            ewh.Set();
                            break;
                    }
                }
                else { }
                //Thread.Sleep(100);
            }
            //String rcvstr = "";
            //Byte[] rcvdata = new Byte[256];
            //Int32 StartPos, StopPos;
            //while (IsOpen)
            //{
            //        try
            //        {
            //                while (serialport.BytesToRead > 0)
            //                {
            //                        Int32 count = serialport.Read(rcvdata, 0, rcvdata.Length);
            //                        rcvstr += System.Text.Encoding.ASCII.GetString(rcvdata, 0, count);
            //                }
            //                StartPos = rcvstr.IndexOf(":");
            //                StopPos = rcvstr.IndexOf("\r\n");
            //                while ((StartPos >= 0) && (StopPos > StartPos))
            //                {
            //                        String framestr = rcvstr.Substring(StartPos + 1, StopPos - StartPos - 1);
            //                        ProcessAFrame(framestr);
            //                        rcvstr = rcvstr.Remove(0, StopPos + 2);
            //                        StartPos = rcvstr.IndexOf(":");
            //                        StopPos = rcvstr.IndexOf("\r\n");
            //                }
            //        }
            //        catch
            //        {
            //        }
            //        Thread.Sleep(100);
            //}

        }

        /// <summary>
        /// 接收、分析、处理响应帧
        /// </summary>
        /// <param name="Command">响应帧中的命令</param>
        /// <param name="Status">响应帧中的状态</param>
        /// <param name="Payload">响应帧中的载荷</param>
        /// <returns></returns>
        private static ErrorCode RcvFrame(out Byte Command, out Byte Status, out Byte[] Payload)
        {
            Command = 0x00;
            Status = 0x00;
            Payload = new Byte[0];
            if (!IsOpen)
            { return ErrorCode.NotOpenError; }
            //接收数据帧
            List<Byte> Frame = new List<byte>();
            Boolean IsDone = false;
            Byte Data = 0x00;
            Boolean flag = true;
            try
            {
                while (!IsDone)
                {
                    Data = (Byte)serialport.ReadByte();
                    switch (Data)
                    {
                        case 0xAA:
                            if (flag)  //帧头，开始
                            {
                                //过滤
                            }
                            else      //数据
                            {
                                Frame.Add(Data);
                                flag = true;
                            }
                            break;
                        case 0x55:
                            if (flag)  //帧尾，结束
                            {
                                //过滤
                                IsDone = true;
                            }
                            else  //数据
                            {
                                Frame.Add(Data);
                                flag = true;
                            }
                            break;
                        case 0xFF:
                            if (flag)  //转义，过滤
                            {
                                flag = false;
                            }
                            else  //数据
                            {
                                Frame.Add(Data);
                                flag = true;
                            }
                            break;
                        default:
                            Frame.Add(Data);
                            break;
                    }


                }
            }
            catch
            { return ErrorCode.ReceiveTimeOut; }
            //分析处理数据帧
            //判断EBV帧长度
            Int32 FrameLength;
            if (Frame[0] > 127)
            {
                FrameLength = (Frame[0] & 0x7F) * 128 + (Frame[1] & 0x7F);
                Command = Frame[2];
            }
            else
            {
                FrameLength = Frame[0];
                Command = Frame[1];
            }
            if (FrameLength != Frame.Count)
            { return ErrorCode.FrameLengthError; }
            //CRC校验
            if (Command > 127)
            {
                if (!CheckCRC(Frame.ToArray()))//校验错误
                { return ErrorCode.CRCError; }
                ////////////////////////////////////////////////////
                Byte[] ReturnData = new Byte[Frame.Count + 2];
                ReturnData[0] = 0xAA;
                for (Int32 i = 0; i < Frame.Count; i++)
                { ReturnData[1 + i] = Frame[i]; }
                ReturnData[ReturnData.Length - 1] = 0x55;
                tempDirection = "接收";
                tempFrameData = ReturnData;
                ewh1.Set();
                //SendAndReceive("接收", ReturnData);
                ////////////////////////////////////////////////////
                //校验正确，移除帧校验
                Frame.RemoveAt(Frame.Count - 1);
                Frame.RemoveAt(Frame.Count - 1);
            }
            else
            {
                //////////////////////////////////////////////////////////////////////////////
                Byte[] ReturnData = new Byte[Frame.Count + 2];
                ReturnData[0] = 0xAA;
                for (Int32 i = 0; i < Frame.Count; i++)
                { ReturnData[1 + i] = Frame[i]; }
                ReturnData[ReturnData.Length - 1] = 0x55;
                tempDirection = "接收";
                tempFrameData = ReturnData;
                ewh1.Set();
                //SendAndReceive("接收", ReturnData);
                //////////////////////////////////////////////////////////////////////////////
            }
            //移除Frame Length
            if (FrameLength > 127)
            {
                Frame.RemoveAt(0);
                Frame.RemoveAt(0);
            }
            else
            {
                Frame.RemoveAt(0);
            }
            //移除Command
            Frame.RemoveAt(0);
            Status = Frame[0];
            //移除Status
            Frame.RemoveAt(0);
            Payload = Frame.ToArray();
            return ErrorCode.AllDone;
        }

        #endregion

        #region MyRegion

        #endregion

        public static class FrequencySetting
        {
            public static Byte FREMODE = 0x00;
            public static Byte FREBASE = 0x01;
            public static UInt16 BF = 0x7303;
            public static Byte CN = 0x10;
            public static Byte SPC = 0x02;
            public static Byte FREHOP = 0x00;

            public static Boolean SetFrequncy(Byte fremode)
            {
                switch (fremode)
                {
                    case 0x00:
                        FREMODE = 0x00;
                        FREBASE = 0x01;
                        BF = 0x7303;
                        CN = 0x10;
                        SPC = 0x02;
                        FREHOP = 0x00;
                        return true;
                    case 0x01:
                        FREMODE = 0x01;
                        FREBASE = 0x01;
                        BF = 0x6903;
                        CN = 0x10;
                        SPC = 0x02;
                        FREHOP = 0x00;
                        return true;
                    case 0x02:
                        FREMODE = 0x02;
                        FREBASE = 0x00;
                        BF = 0x6C2E;
                        CN = 0x0C;
                        SPC = 0x04;
                        FREHOP = 0x00;
                        return true;
                    case 0x03:
                        FREMODE = 0x03;
                        FREBASE = 0x00;
                        BF = 0x7260;
                        CN = 0x01;
                        SPC = 0x02;
                        FREHOP = 0x00;
                        return true;
                    case 0x04:
                        return false;
                    default:
                        return SetFrequncy(0x00);
                }
            }

            public static Boolean SetFrequncy(Byte[] FrequencyData)
            {
                switch (FrequencyData[0])
                {
                    case 0x00:
                    case 0x01:
                    case 0x02:
                    case 0x03:
                        return SetFrequncy(FrequencyData[0]);
                    case 0x04:
                        try
                        {
                            FREMODE = 0x04;
                            FREBASE = FrequencyData[1];
                            BF = (UInt16)(FrequencyData[2] * 256 + FrequencyData[3]);
                            CN = FrequencyData[4];
                            SPC = FrequencyData[5];
                            FREHOP = FrequencyData[6];
                            return true;
                        }
                        catch
                        { return false; }
                    default:
                        return SetFrequncy(0x00);
                }
            }

            public static Byte[] GetFrequncy()
            {
                return new Byte[] { FREMODE, FREBASE, (Byte)(BF / 256), (Byte)(BF % 256), CN, SPC, FREHOP };
            }
        }

    }

    public enum ErrorCode
    {
        AllDone = 0x00,
        SerialPortError = 0x01,
        SendTimeOut = 0x02,
        NotOpenError = 0x03,
        ReceiveTimeOut = 0x04,
        CRCError = 0x05,
        FrameLengthError = 0x06,
        CommandError = 0x07,
        StatusError = 0x08,
        PayloadError = 0x09,
        DataLengthError = 0x0A,
        ParameterError = 0x0B,
        ReadOnlyError = 0x0C,
        OtherErrorCode = 0x10,
        OverflowErrorCode = 0x11,
        LockErrorCode = 0x12,
        PowerLackErrorCode = 0x13,
        UnknownErrorCode = 0x14,
        OverflowSelectError = 0x20,
        ReadOnlySelectError = 0x21,
        OtherSelectError = 0x22,
        UnknowSelectError = 0x23,
        SRecordSelectError = 0x24,
        UnknownError = 0xFF
    }



}


